<!DOCTYPE html>

<head>
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title>
</head>

<body>
    <script>
        // http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
        // exampl1中闭包函数function被alert调用，也就是在全局环境中调用，所以this.window中的this是全局变量也就是window，所以打印出是全局变量name
        /**
        object.getNameFunc()返回的是一个匿名函数，之后object.getNameFunc()()相当于立马执行即在全局环境中调用该匿名函数，所以this指向的是window。
        **/
        console.log(typeof ('sdsd'))
        console.log(232, 444)

        function log() {
            var args = Array.prototype.slice.apply(arguments);
            args.unshift('(app)');

            console.log.apply(console, args);
        };
        log(4, 3)

        let array = [1]
        let obj = {}
        console.log(Object.prototype.__proto__)
        console.log(Object.__proto__ == Function.prototype)
        console.log(Function.__proto__ == Function.prototype)
        console.log(Function.__proto__ === Function.prototype) // true
        console.log(Object.__proto__) // true
        console.log(Object.__proto__)
        console.log(array.constructor == Array)
        console.log(array.__proto__ == Array.prototype)

        function Person() {
            this.name = 'sds'
        };
        console.log(Person.prototype) //Person{}
        console.log(typeof Person.prototype) //Object
        console.log(typeof Function.prototype) // Function，这个特殊
        console.log(typeof Object.prototype) // Object
        console.log(typeof Function.prototype.prototype) //undefined
        var name = "The Window";

        var object = {
            name: "My Object",

            getNameFunc: function () {
                return function () {
                    return this.name;
                };

            }

        };
        console.log('example1');
        console.log(object.getNameFunc()());
        var name = "The Window";

        var object = {
            name: "My Object",

            getNameFunc: function () {
                var that = this;
                return function () {
                    return that.name;
                };

            }

        };
        console.log('example2');
        console.log(object.getNameFunc()());

        function foo() {
            var a = 2;

            function bar() {
                console.log(a);
            }
            return bar;
        }
        var baz = foo();
        baz(); // 
        // 或者如下方式，foo是一个函数，foo()是foo执行后，也就是返回了bar，所以baz是bar函数，下面baz()就是bar函数执行
        //  var baz = foo;
        //  baz()(); // 2

        /* https://www.cnblogs.com/yifeng555/p/8455414.html */

        console.log('example2-')
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr[i] = function () {
                return i;
            }
        }
        console.log(arr[3]()); // 10
        console.log('example2--')
        var arr = [];
        for (let i = 0; i < 10; i++) {
            arr[i] = function () {
                return i;
            }
        }
        console.log(arr[3]()); // 3
        console.log('example3')
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr[i] = function (i) {
                return function () {
                    return i;
                }
            }(i)
        }
        console.log(arr[3]()); //3

        console.log('example5')
        var arr1 = [];
        for (var i = 0; i < 10; i++) {
            arr1[i] = function (i) {
                return i;
            }(i)
        }
        console.log(arr1[4]); //3
        console.log('example4')
        var arr1 = [];
        for (let i = 0; i < 10; i++) {
            arr1[i] = function () {
                return i;
            }
        }
        console.log(arr1[3]()); //3
        console.log('example10')

        function Animal() { }
        Animal.prototype.species = "动物";

        function extend2(Child, Parent) {
            var p = Parent.prototype;
            var c = Child.prototype;
            for (var i in p) {
                c[i] = p[i];
            }
            c.uber = p;
        }

        console.log('example5')
        color = "red";
        var obj2 = {
            color: "blue",
            getColor: function () {
                function displayColor() {
                    return this.color;
                }
                return displayColor(); // 注意：这里范湖IDE是displayCoror()的执行结果，不是displayColor函数本身
            }
        }
        console.log(obj2.getColor());
        console.log('example6')
        var name = "The Window";
        var object = {
            name: "My Object",
            getNameFunc: function () {
                return function () {
                    return this.name;
                };
            }
        };
        console.log(object.getNameFunc()());
        console.log('example7')
        var myObject = {
            foo: "bar",
            func: function () {
                var self = this;
                console.log("outer func:  this.foo = " + this.foo);    //输出 bar
                console.log("outer func:  self.foo = " + self.foo);    //输出 bar
                (function () {
                    console.log("inner func:  this.foo = " + this.foo);   //输出 undefined
                    console.log("inner func:  self.foo = " + self.foo);   //输出 bar
                })();
            }
        };
        myObject.func();
        console.log('example8')
        var nimo = {}
        nimo.fn2 = function () {
            console.log(this);//Object nimo {fn2: function} 
            +function () {
                console.log(this)//window
            }()

        }
        nimo.fn2();
        console.log('')
        console.log('example11')
        function f1() {
            //闭包f2被外引用始终存在内存中，而它所依赖的f1也会始终存在
            //所以n,m都是始终存在，删除闭包直接f1=null；
            var n = 1, m = 100;
            madd = function () {
                m += 10;
                console.log(m);
            }  //全局变量madd
            function f2() {
                n += 1;
                console.log(n);
            }
            return f2;
        }
        var a = f1(); //将子函数返回赋值给了变量a
        a(); // 2
        madd(); // 110
        //madd的值是一个匿名函数，同时是一个闭包，实现了外部对函数内部进行操作
        a(); // 3
    </script>
</body>

</html>